package com.xiaomaoguai.date;

import com.google.common.collect.Lists;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.time.FastDateFormat;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 日期工具类
 *
 * @ ClassName: DateUtils.java
 * @ Author: WeiHui-Z
 * @ Date: 2016/12/29 15:56
 * @ Version: v1.0.0
 */
public final class DateUtils implements DatePattern {

	private static final Logger LOGGER = LoggerFactory.getLogger(DateUtils.class);

	/**
	 * 私有化构造函数
	 */
	private DateUtils() {
	}

	/**
	 * 得到当前月有多少天
	 *
	 * @param month 月份
	 * @return 天数
	 */
	public static int getCurrentMonthDayNum(String month) {
		String string = format(new Date(), YYYY);
		boolean renYear = isLeapYear(Integer.parseInt(string));
		boolean contains = DAY31.contains(month);
		if (contains) {
			return 31;
		}
		boolean contains2 = DAY30.contains(month);
		if (contains2) {
			return 30;
		}
		if (renYear) {
			return 29;
		} else {
			return 28;
		}
	}

	public static void main(String[] args) {
		System.out.println(format(new Date(), YYYY_MM_DD_D));

		int monthDays = getMonthDays("20150524", "yyyyMMdd");
		System.out.println(monthDays);

		System.out.println(getDatesYear(new Date()));

		System.out.println(getDatesMonth(new Date()));
	}

	/**
	 * 格式化日期
	 * <pre>
	 *      1.使用 commons-lang3 的 格式化日期工具类-防止并发
	 * </pre>
	 *
	 * @param date    日期
	 * @param pattern 模式
	 * @return 格式化后的日期
	 */
	public static String format(Date date, String pattern) {
		//DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss:sss") 调用的 FastDateFormat
		return FastDateFormat.getInstance(pattern).format(date);
	}

	/**
	 * 得到日期的月份的天数
	 *
	 * @param date    日期
	 * @param pattern 模式
	 * @return 月份的天数
	 */
	public static int getMonthDays(String date, String pattern) {
		Date time = parser(date, pattern);
		int year = Integer.parseInt(getDatesYear(time));
		String month = getDatesMonth(time);
		boolean renYear = isLeapYear(year);
		boolean contains = DAY31.contains(month);
		if (contains) {
			return 31;
		}
		boolean contains2 = DAY30.contains(month);
		if (contains2) {
			return 30;
		}
		if (renYear) {
			return 29;
		} else {
			return 28;
		}
	}

	/**
	 * 得到月的每一天
	 *
	 * @param date        日期
	 * @param srcPattern  原始模式
	 * @param destPattern 目的模式
	 * @return 月的每一天
	 */
	public static List<String> getMonthEachDay(String date, String srcPattern, String destPattern) {
		List<String> list = new ArrayList<>();
		Date time = parser(date, srcPattern);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(time);
		calendar.add(Calendar.MONTH, 1);
		Date nextMonthTime = calendar.getTime();
		calendar.setTime(time);
		while (time.getTime() < nextMonthTime.getTime()) {
			list.add(format(time, destPattern));
			calendar.add(Calendar.DAY_OF_YEAR, 1);
			time = calendar.getTime();
		}
		return list;
	}

	/**
	 * 字符串转日期
	 *
	 * @param date    字符串日期
	 * @param pattern 模式
	 * @return 日期
	 */
	public static Date parser(String date, String pattern) {
		Date result = null;
		try {
			result = FastDateFormat.getInstance(pattern).parse(date);
		} catch (ParseException e) {
			LOGGER.error("解析日期出错", e);
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 得到昨天的日期
	 *
	 * @param date 日期
	 * @return 获取昨天
	 */
	public static Date getYesterday(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_YEAR, -1);
		return calendar.getTime();
	}

	/**
	 * 得到昨天的日期的字符串
	 *
	 * @param date    日期
	 * @param pattern 模式
	 * @return 昨天的日期的字符串
	 */
	public static String getYesterdayStr(Date date, String pattern) {
		return new SimpleDateFormat(pattern).format(getYesterday(date));
	}

	/**
	 * 得到昨天的日期
	 *
	 * @param date 日期
	 * @return 获取昨天
	 */
	public static Date getYesterday(String date, String pattern) {
		Date today = parser(date, pattern);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(today);
		calendar.add(Calendar.DAY_OF_YEAR, -1);
		return calendar.getTime();
	}

	/**
	 * 得到明天的日期
	 *
	 * @param date 日期
	 * @return 得到明天的日期
	 */
	public static Date getTomorrow(Date date) {
		return getDaysBefore(date, +1);
	}

	/**
	 * @param date    日期
	 * @param pattern 模式
	 * @return 得到明天的日期
	 */
	public static Date getTomorrow(String date, String pattern) {
		return getDaysBefore(parser(date, pattern), +1);
	}

	/**
	 * 判断当前日期是不是日期形式
	 *
	 * @param date    日期
	 * @param pattern 模式
	 * @return true | false
	 */
	public static boolean isDate(String date, String pattern) {
		SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
		try {
			dateFormat.parse(date);
		} catch (ParseException e) {
			LOGGER.error("解析日期出错", e);
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 得到日期的年份
	 *
	 * @param date 日期
	 * @return 年份
	 */
	public static String getDatesYear(Date date) {
		return format(date, YYYY);
	}

	/**
	 * 得到日期的月份
	 *
	 * @param date 日期
	 * @return 月份
	 */
	public static String getDatesMonth(Date date) {
		return format(date, MM);
	}

	/**
	 * 判断年份是否是闰年
	 *
	 * @param year 年份
	 * @return true | false
	 */
	public static boolean isLeapYear(int year) {
		return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
	}

	/**
	 * 得到日期之前或之后的一个字符串日期
	 *
	 * @param date    日期
	 * @param days    天数
	 * @param pattern 模式
	 * @return 字符串日期
	 */
	public static String getDaysBefore(Date date, int days, String pattern) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_YEAR, days);
		return format(calendar.getTime(), pattern);
	}

	/**
	 * 得到日期之前或之后的一个日期
	 *
	 * @param date 日期
	 * @param days 天数
	 * @return 日期
	 */
	public static Date getDaysBefore(Date date, int days) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_YEAR, days);
		return calendar.getTime();
	}

	/**
	 * 计算两个日期之间的天数
	 *
	 * @param start 开始日期
	 * @param end   结束日期
	 * @return 天数
	 */
	public static int countDaysBetween(Date start, Date end) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(start);
		long time1 = cal.getTimeInMillis();
		cal.setTime(end);
		long time2 = cal.getTimeInMillis();
		long daysInterval = (time2 - time1) / (1000 * 3600 * 24);
		return Integer.parseInt(String.valueOf(daysInterval));
	}

	/**
	 * 计算两个日期之间的天数
	 *
	 * @param start   开始日期
	 * @param end     结束日期
	 * @param pattern 日期模式
	 * @return 天数
	 */
	public static int countDaysBetween(String start, String end, String pattern) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(parser(start, pattern));
		long time1 = cal.getTimeInMillis();
		cal.setTime(parser(end, pattern));
		long time2 = cal.getTimeInMillis();
		long daysInterval = (time2 - time1) / (1000 * 3600 * 24);
		return Integer.parseInt(String.valueOf(daysInterval));
	}

	/**
	 * 得到当期日期的起始时间的字符串
	 *
	 * @param date    日期
	 * @param pattern 模式
	 * @return 日期的起始时间的字符串
	 */
	public static String getDateBeginTime(Date date, String pattern) {
		return new DateTime(date).withTimeAtStartOfDay().toString(pattern);
	}

	/**
	 * 得到当期日期的结束时间的字符串
	 *
	 * @param date    日期
	 * @param pattern 模式
	 * @return 日期的结束时间的字符串
	 */
	public static String getDateEndTime(Date date, String pattern) {
		return new DateTime(date).millisOfDay().withMaximumValue().toString(pattern);
	}

	/**
	 * @param start         开始日期
	 * @param end           结束日期
	 * @param srcPattern    开始日期的格式
	 * @param returnPattern 结束日期的格式
	 * @return 天列表
	 */
	public static List<String> getDaysStart2End(String start, String end, String srcPattern, String returnPattern) {
		List<String> result = Lists.newArrayList();
		Date startDate = parser(start, srcPattern);
		Date endDate = parser(end, srcPattern);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startDate);
		while (startDate.getTime() <= endDate.getTime()) {
			calendar.add(Calendar.DAY_OF_YEAR, 1);
			String key = format(startDate, returnPattern);
			result.add(key);
			startDate = calendar.getTime();
		}
		return result;
	}

	/**
	 * @param start      开始日期
	 * @param end        结束日期
	 * @param srcPattern 开始日期的格式
	 * @return 开始日期 到 结束日期 间的每一天
	 */
	public static List<Date> getDatesBetween(String start, String end, String srcPattern) {
		List<Date> result = Lists.newArrayList();
		Date startDate = parser(start, srcPattern);
		Date endDate = parser(end, srcPattern);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startDate);
		while (startDate.getTime() <= endDate.getTime()) {
			calendar.add(Calendar.DAY_OF_YEAR, 1);
			result.add(startDate);
			startDate = calendar.getTime();
		}
		return result;
	}

	public static List<String> getMonthsBetween(String start, String end, String pattern) {
		List<String> result = Lists.newArrayList();
		Date startDate = parser(start, pattern);
		Date endDate = parser(end, pattern);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startDate);
		while (startDate.getTime() <= endDate.getTime()) {
			calendar.add(Calendar.MONTH, 1);
			String key = format(startDate, "yyyyMM");
			result.add(key);
			startDate = calendar.getTime();
		}
		return result;
	}

}
